教程|编写一个 Substrate 模块
自己创建一个 Pallet
在本教程中, 你将编写一个存在于其自身 crate(包装箱)里的 Substrate 模块,并将其包含在基于 substrate-node-template
的节点中。
安装 Node Template
当你学习完教程:创建你的第一条Substrate链[1] 之后,你应该已经在计算机上编译了 Substrate Node Template[2] 的 v2.0.0-alpha.8
版本,如果没有的话, 请先学习完教程。
“如果你是有经验的开发人员,倾向于选择跳过该教程,建议你可以根据自述文件中的说明安装节点模板。
克隆 Pallet 模板
我们不会将 Pallet(模块)直接写为节点模板的一部分,而是写成一个单独的 Rust crate。这种形式让我们可以和节点分开发布 Pallet,也可以让其他人轻松的将该 Pallet 导入自己的 Substrate Runtime。
在你的节点模板的 pallets
目录中克隆 Substrate pallet template:
cd pallets
git clone -b v2.0.0-alpha.8 https://github.com/substrate-developer-hub/substrate-pallet-template test-pallet
“在本教程中,我们将 pallet template (模块模板) 放在 node template (节点模板)的目录结构中。这种形式不是必须的,你可以将 pallet template 放置在任意位置。另一种流行的做法是将其作为 node template 的同级。
Substrate Pallet 模板
让我们从 Cargo.toml
文件开始探索 Substrate Pallet template。
重命名 crate
在 Cargo.toml
文件中, 你可以更新 crate 的名称和作者身份。在本教程中,我们集中讲如何创建和使用 pallet (模块),而不是编写 pallet (模块)逻辑。我们称之为 test-pallet
。
Cargo.toml
的开头是这样展示的:
pallets/test-pallet/Cargo.toml
[package]
authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
description = 'Substrate FRAME pallet template'
edition = '2018'
homepage = 'https://substrate.io'
license = 'Unlicense'
name = 'test-pallet'
repository = 'https://github.com/paritytech/substrate/'
version = '2.0.0-alpha.8'
编译 Template Pallet
“如果你已按照本教程的步骤进行操作 ,并将模板模块克隆到节点模板的
pallets
目录中,则需要将模板模块添加到Cargo.toml
文件的workspace.members
数组中。在节点模板目录的根目录中;你将需要包括路径和包的名称,所以需要将此元素添加到members
数组中:'pallets/test-pallet',
。
你应该能够使用以下命令成功编译 Substrate pallet template :
cd test-pallet
cargo build --release
模块的 std
功能
在这个 pallets/test-pallet/Cargo.toml
文件中,你会注意到关于 "std
功能" 的几行内容,在 Rust 中, 当你启用 “std
功能” 时,就可以让你的项目访问 Rust标准库[3]。这在构建本机二进制时非常好用。
但是, Substrate 也将 runtime 代码构建到 WebAssembly (Wasm)。在这种情况下, 我们使用 cargo 功能禁用 Rust 标准库。因此,我们用于 Pallet (模块)及整个 runtime 时的所有依赖项都必须能够使用 `no_std`[4] 功能。Cargo.toml
文件会告诉模块的依赖项,仅在该模块还使用 std
功能时才使用其 std
功能, 如下所示:
pallets/test-pallet/Cargo.toml
[features]
default = ['std']
std = [
'codec/std',
'frame-support/std',
'frame-system/std',
]
Substrate 的依赖性需保持一致
所有的 Substrate 模块都是依赖于一些较低级别的 FRAME 库,例如 frame-system
和 frame-support
。这些库是从 crates.io 中提取的。当人们构建自己的基于 FRAME 的 runtime 时, 他们还将依赖于这些低级库. 并且你需要确保 pallet 和 runtime 之间保持一致性依赖关系。
pallets/test-pallet/Cargo.toml
# --snip--
[dependencies.frame-support]
git = 'https://github.com/paritytech/substrate.git'
default-features = false
tag = 'v2.0.0-alpha.8'
从上面的代码片段中,我们看到该 pallet template 取决于低级库的版本 2.0.0-alpha.8
。因此它可以在同样依赖于 2.0.0-alpha.8
的 runtime 中使用。
模块的开发依赖
Cargo.toml
文件的最后一部分指定了开发依赖项。这些依赖项是在模块的测试中需要用到的,而不是实际模块本身需要。
pallets/test-pallet/Cargo.toml
# --snip--
[dev-dependencies.sp-core]
git = 'https://github.com/paritytech/substrate.git'
default-features = false
tag = 'v2.0.0-alpha.8'
你可以通过以下命令来确认 Substrate pallet template 中的测试通过了:
cargo test
当更新模块来包含你自定义的逻辑时, 你可能需要向 Cargo.toml
文件添加自己的依赖项。
将模块添加到节点
当我们的模块以及编译并通过了测试,可以开始准备将其添加到我们的节点中。
“如果你对包含和使用其他 crate 还不熟悉, 请参阅 the Cargo book[5] 以了解更多信息。
我们首先在节点的 runtime Cargo.toml
中将新创建的 crate 添加为依赖项,然后告诉模块仅在 runtime 本身构建时,才构建其 std
功能,如下所示:
runtime/Cargo.toml
# --snip--
[dependencies.test-pallet]
default-features = false
path = '../pallets/test-pallet'
# toward the bottom
[features]
default = ['std']
std = [
'test-pallet/std',
# --snip--
]
“你必须设置为
default_features = false
这样你的 runtime 才能成功编译为 Wasm。
接下来,我们通过将 test_pallet
添加到 construct_runtime!
宏中,来更新 runtime/src/lib.rs
,以实际使用我们新的 runtime pallet。
runtime/src/lib.rs
// add the following code block
impl test_pallet::Trait for Runtime {
type Event = Event;
}
// --snip--
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
// --snip--
// add the following line
TestPallet: test_pallet::{Module, Call, Storage, Event<T>},
}
);
运行节点
至此,你已经将模块打包在自己的模块包中,并包含在节点的 runtime 中。
确保你返回了节点模板的根目录,然后使用以下命令编译并运行节点:
cargo build --release
清除所有现有的开发链 (在提示时输入 y
):
./target/release/node-template purge-chain --dev
启动节点:
./target/release/node-template --dev
最后,启动 Polkadot-JS Apps connecting to your local node[6] 确保模块按预期工作。
“注意: 你还可以通过以下方式在 Polkadot-JS Apps 中手动设置节点 URL: 导航到设置标签, 并将要连接的远程节点/端点设置为本地节点。
发布模块
一旦你的模块不再处于测试阶段,你应该考虑将其发布到 GitHub 或者 crates.io。
在 GitHub 上发布
要在 GitHub上发布, 你需要创建GitHub存储库[7]并发布模块代码[8] 。
在 Crates.io 上发布
Crates.io 允许未经许可的发布。可以按照他们发布指南学习如何在Crate.io上发布[9]。
更新 Runtime 依赖项
现在 Pallet 已经发布在 GitHub 或 crates.io,或者两个地方都发了,我们可以更新 runtime 以使用发布的代码,而不是硬编码的文件系统路径。
GitHub 的依赖项
runtime/Cargo.toml
[dependencies.your-pallet-name]
default_features = false
git = 'https://github.com/your-username/your-pallet'
branch = 'master'
# You may choose a specific commit or tag instead of branch
# rev = '<git-commit>'
# tag = '<some tag>
Crates.io 的依赖项
runtime/Cargo.toml
[dependencies.your-pallet-name]
default_features = false
version = 'some-compatible-version'
完善构建
再次编译,并且注意 Cargo 现在从 GitHub 或 crates.io 抓取你的 Pallet 而不是使用本地文件。
下一步
恭喜! 你已经成功编写并发布了一个 Substrate 模块在自己的 Rust 包中。其他的区块链开发者只需要在 Cargo.toml
文件中简单的使用 4 行代码并更新其 runtime 的 lib.rs
文件,就可以在他们的 runtime 中轻松使用你的 pallet。
了解更多
我们还有 很多教程[10] 关于 Substrate 开发的概念和技术。 更多信息关于 runtime 开发技巧和模式,请参阅 Substrate Recipes[11].
参考资料
The Cargo book[12] 更多关于 Rust and WebAssembly[13] 的信息
参考链接
创建你的第一条Substrate链: https://www.substrate.io/tutorials/pallet-in-own-crate/tutorials/create-your-first-substrate-chain/v2.0.0-alpha.8
[2]Substrate Node Template: https://github.com/substrate-developer-hub/substrate-node-template
[3]Rust标准库: https://doc.rust-lang.org/std/
[4]no_std
: https://rust-embedded.github.io/book/intro/no-std.html
the Cargo book: https://doc.rust-lang.org/cargo/guide/creating-a-new-project.html
[6]Polkadot-JS Apps connecting to your local node: https://polkadot.js.org/apps/#/explorer?rpc=ws://127.0.0.1:9944
[7]创建GitHub存储库: https://help.github.com/en/articles/create-a-repo
[8]发布模块代码: https://help.github.com/en/articles/pushing-to-a-remote
[9]如何在Crate.io上发布: https://doc.rust-lang.org/cargo/reference/publishing.html
[10]很多教程: https://www.substrate.io/tutorials
[11]Substrate Recipes: https://substrate.dev/recipes/
[12]The Cargo book: https://doc.rust-lang.org/stable/cargo/
[13]Rust and WebAssembly: https://rustwasm.github.io/
原文:https://www.substrate.io/tutorials/pallet-in-own-crate/v2.0.0-alpha.8
翻译:PolkaWorld 社区
欢迎学习 Substrate:
https://substrate.dev/
关注 Substrate 进展:
https://github.com/paritytech/substrate
关注 Polkadot 进展:
https://github.com/paritytech/polkadot
申请 Bootcamp:
https://bootcamp.web3.foundation/
更多内容:
在 Substrate 中为你的 runtime 添加合约模块
扫码关注公众号,回复 “1” 加入波卡群
关注 PolkaWorld
发现 Web 3.0 时代新机遇
点个 “在看” 再走吧!